package com.globallogic.javatrainings.sergiiivanov.controller;

import java.util.HashMap;
import java.util.Random;

import com.globallogic.javatrainings.sergiiivanov.model.Const;
import com.globallogic.javatrainings.sergiiivanov.model.Course;
import com.globallogic.javatrainings.sergiiivanov.model.Lecture;
import com.globallogic.javatrainings.sergiiivanov.model.Lecture.LectureType;
import com.globallogic.javatrainings.sergiiivanov.model.Room;
import com.globallogic.javatrainings.sergiiivanov.model.Room.RoomType;
import com.globallogic.javatrainings.sergiiivanov.model.Student;
import com.globallogic.javatrainings.sergiiivanov.model.University;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityFailure;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityWarning;
import com.globallogic.javatrainings.sergiiivanov.view.GUI;

public class UniversityTemplates {

    private static final String JAVA_ADVANCED = "Java Advanced";
    private static final String CPP = "C++";
    private static final String JAVA_EE = "Java EE";
    private static final String JAVA_BASICS = "Java Basics";

    /**
     * <pre>
     * builds University "GL Java Training"
     *  with 2 buildings 
     *      with 5 rooms each 
     *            1 other,
     *            1 lab,
     *            3 auditoriums;
     *  adds 
     *    10 students,
     *     3 teachers,
     *     2 personnel,
     *     4 courses
     *       with some lectures;
     *  assigns all students to all courses;
     *  assigns teachers to courses;
     *  adds one random score per student per lecture;
     *  appoint rooms to all lectures;
     *  assign personnel to rooms;
     * </pre>
     * @return filled University("GL Java Training")
     * @throws Exception
     */
    public static University universityTemplte1() throws UniversityFailure, UniversityWarning {

        University u = new University("GL Java Training");

        u.buildings.addBuilding("Main Office");
        u.buildings.addBuilding("Coliseum");
        u.buildings.getBuildingByIndex(0).addRoom("Main Reception");
        u.buildings.getBuildingByIndex(0).addRoom("Main C++ lab 1", RoomType.LABORATORY, 10);
        u.buildings.getBuildingByIndex(0).addRoom("Main C++ lab 2", RoomType.LABORATORY, 20);
        u.buildings.getBuildingByIndex(0).addRoom("Main Class 1", RoomType.AUDITORIUM, 10);
        u.buildings.getBuildingByIndex(0).addRoom("Main Class 2", RoomType.AUDITORIUM, 20);
        u.buildings.getBuildingByIndex(1).addRoom("Coliseum Teachers");
        u.buildings.getBuildingByIndex(1).addRoom("Coliseum Java lab 1", RoomType.LABORATORY, 10);
        u.buildings.getBuildingByIndex(1).addRoom("Coliseum Java lab 2", RoomType.LABORATORY, 20);
        u.buildings.getBuildingByIndex(1).addRoom("Coliseum Class 2", RoomType.AUDITORIUM, 10);
        u.buildings.getBuildingByIndex(1).addRoom("Coliseum Class 3", RoomType.AUDITORIUM, 20);

        u.courses.addCource(JAVA_BASICS, Const.Discipline.Java6);
        u.courses.addCource(JAVA_EE, Const.Discipline.Java7);
        u.courses.addCource(CPP, Const.Discipline.Cpp);
        u.courses.addCource(JAVA_ADVANCED, Const.Discipline.Java6);

        fillLectureByPattern(u.courses.getCourseByIndex(0), "5l 2p 1e");
        fillLectureByPattern(u.courses.getCourseByIndex(1), "3l 1p 5l 2p 1e");
        fillLectureByPattern(u.courses.getCourseByIndex(2), "8l 2p 1e 8l 2p 1e");
        appointRooms(u);

        u.teachers.addPerson("Lars Vogel", "050 555 00 55", "have.no.idea@but.eclipse");
        u.teachers.getTeacherByIndex(0).addResumeEntry("1998;GL Java courses;Finished with reward".split(";"));
        u.teachers.getTeacherByIndex(0).addResumeEntry("2010;Eclipse Community Awards;Winner".split(";"));
        u.teachers.addPerson("James Gosling", "050 333 00 33", "ive.written.it@from.scratch");
        u.teachers.getTeacherByIndex(1).addResumeEntry("1977;University of Calgary;B.Sc in Computer Science".split(";"));
        u.teachers.getTeacherByIndex(1).addResumeEntry("1984-2010;Sun Microsystems, Inc.;Was creating Java".split(";"));
        u.teachers.addPerson("Patrick Naughton", "050 222 00 22", "show.me.path@to.j2ee");

        u.courses.getCourseByIndex(0).setTeacher(u.teachers.getTeacherByIndex(0));
        u.courses.getCourseByIndex(1).setTeacher(u.teachers.getTeacherByIndex(2));
        u.courses.getCourseByIndex(2).setTeacher(u.teachers.getTeacherByIndex(1));
        u.courses.getCourseByIndex(3).setTeacher(u.teachers.getTeacherByIndex(1));

        u.students.addPerson("Thomas Anderson", "555 555 55 55", "neo@zeon.undercity");
        u.students.getStudentByIndex(0).addResumeEntry("1994;Meta Cortex;it was a dream".split(";"));
        u.students.addPerson("John Connor", "000 000 00 00 0", "hiding.in.ca@from.skynet");
        u.students.getStudentByIndex(1).addResumeEntry("1995;Outsides;Survived against T-1000".split(";"));
        u.students.addPerson("Zero Cool", "000 000 00 00 1", "aka.crash.override@for.burn");
        u.students.getStudentByIndex(2).addResumeEntry("1988;Home;Hacked 1507 PCs at once".split(";"));
        u.students.addPerson("Charles A. Forbin", "000 1111 1111", "ive.build@the.collosus");
        u.students.getStudentByIndex(3).addResumeEntry("1970;Colosus;Creator and hostage ".split(";"));
        u.students.addPerson("Miles Harding", "000 2222 0000", "jigsaw@puzzle.stable");
        u.students.getStudentByIndex(4).addResumeEntry("1984;ArchTech;Constructons Engineer".split(";"));
        u.students.addPerson("Ben Jabituya", "000 1234 0000", "weve.made@number.five");
        u.students.getStudentByIndex(5).addResumeEntry("1986;U.S. military;Robotics and Electronics Engineer".split(";"));
        u.students.addPerson("Pavel Chekov", "000 0000 xxxx", "wicktor@enterprise.space");
        u.students.getStudentByIndex(6).addResumeEntry("2260;USS Enterprise (NCC-1701);Navigation Engineer".split(";"));
        u.students.addPerson("Johnny Mnemonic", "000 0000 0000", "owned.by@ralfi");
        u.students.getStudentByIndex(7).addResumeEntry("2021;Ralfi;Mnemonic Courier".split(";"));
        u.students.addPerson("Douglas Hall", "000 1515 0000", "ive.opened@15th.floor");
        u.students.getStudentByIndex(8).addResumeEntry("1995;Fullers VR;Suspect".split(";"));
        u.students.addPerson("Allen Hobby", "111 0000 0000", "professor@blue.fairy");
        u.students.getStudentByIndex(9).addResumeEntry("-;Cybertronics;A.I. Designer".split(";"));
        for (Course c : u.courses.getCourses()) {
            for (Student s : u.students.getStudents()) {
                c.enrollStudent(s);
            }
        }
        u.personnel.addPersonnel("Forest Gump", "333 333 33 33", "bus.stop@somewhere");
        u.personnel.getPersonnelByIndex(0).addResumeEntry("1982;Bus Stop;Storyteller".split(";"));
        u.personnel.addPersonnel("Raymond Babbitt", "123 4567 8901", "rainman@la.babbit");
        u.personnel.getPersonnelByIndex(1).addResumeEntry("1988;Las Vegas;Pocker Cheater".split(";"));

        for (Room r : u.buildings.getBuildingByIndex(0).getRooms()) {
            r.setResponsiblePerson(u.personnel.getPersonnelByIndex(0));
        }
        for (Room r : u.buildings.getBuildingByIndex(1).getRooms()) {
            r.setResponsiblePerson(u.personnel.getPersonnelByIndex(1));
        }

        addScores(u);
        return u;
    }

    private static void appointRooms(University u) throws UniversityWarning, UniversityFailure {
        /*
         * u.courses.addCource(JAVA_BASICS, Discipline.Java6);
         * u.courses.addCource(JAVA_EE, Discipline.Java7);
         * u.courses.addCource(CPP, Discipline.Cpp);
         * u.courses.addCource(JAVA_ADVANCED, Discipline.Java6);
         */
        appointCourse(u, 0, 1, 2, 4);
        appointCourse(u, 1, 1, 2, 4);
        appointCourse(u, 2, 0, 2, 4);
        appointCourse(u, 3, 1, 2, 4);
    }

    private static void appointCourse(
            University u,
            int course,
            int buildInd,
            int roomP,
            int roomL
            ) throws UniversityFailure, UniversityWarning {

        Room roomLec = u.buildings.getBuildingByIndex(buildInd).getRoomByIndex(roomL);
        Room roomPra = u.buildings.getBuildingByIndex(buildInd).getRoomByIndex(roomP);
        for (Lecture l : u.courses.getCourseByIndex(course).getLectures()) {
            if (l.getLectureType().equals(LectureType.PRACTICE)) {
                l.setRoom(roomPra);
            } else {
                l.setRoom(roomLec);
            }
        }
    }

    private static void addScores(University u) throws UniversityWarning {
        String[] reasonsPositive = { "nice hair", "speaks good", "funny one", "likes my books", "can read", "loves cats",
                "does it good", "have a mission", "sees problems" };
        String[] reasonsNegative = { "mumbles", "has evil look", "grimacing", "scary face", "bad hair", "too fat", "idiot",
                "complicated one", "primadonna", "thinks faster than me" };

        Random r = new Random();
        for (Course c : u.courses.getCourses()) {
            for (Student s : c.getEnrolledStudents()) {
                for (Lecture l : c.getLectures()) {
                    int score = Const.MIN_SCORE + r.nextInt(Const.MAX_SCORE - Const.MIN_SCORE);
                    String reason = "";
                    if (score > ((Const.MAX_SCORE - Const.MIN_SCORE) / 2)) {
                        reason = reasonsPositive[r.nextInt(reasonsPositive.length)];
                    } else {
                        reason = reasonsNegative[r.nextInt(reasonsNegative.length)];
                    }
                    s.addScore(l, score, reason);
                }
            }
        }
    }

    private static void fillLectureByPattern(Course c, String pattern) {
        String[] patternSplit = pattern.split(" ");
        HashMap<LectureType, Integer> counter = new HashMap<LectureType, Integer>();
        int numberOfLectures;
        LectureType lectureType;
        counter.put(LectureType.LECTURE, 1);
        counter.put(LectureType.PRACTICE, 1);
        counter.put(LectureType.EXAMINATION, 1);
        for (int indexInPattern = 0; indexInPattern < patternSplit.length; indexInPattern++) {
            numberOfLectures = 0;
            if (patternSplit[indexInPattern].endsWith("l")) {
                lectureType = LectureType.LECTURE;
                numberOfLectures = Integer
                        .parseInt(patternSplit[indexInPattern].replace("l", ""));
            } else if (patternSplit[indexInPattern].endsWith("p")) {
                lectureType = LectureType.PRACTICE;
                numberOfLectures = Integer
                        .parseInt(patternSplit[indexInPattern].replace("p", ""));
            } else if (patternSplit[indexInPattern].endsWith("e")) {
                lectureType = LectureType.EXAMINATION;
                numberOfLectures = Integer
                        .parseInt(patternSplit[indexInPattern].replace("e", ""));
            } else {
                GUI.getGUI().show("Wrong pattern element - "
                        + patternSplit[indexInPattern]);
                continue;
            }
            for (int indexLecture = 0; indexLecture < numberOfLectures; indexLecture++) {
                try {
                    c.addLecture(
                            lectureType.getRepresentation() + " " + counter.get(lectureType) + "." + (indexLecture + 1),
                            lectureType,
                            "autogenerated"
                            );
                } catch (UniversityWarning e) {
                    GUI.getGUI().show("Failed to add lecture to course " + c.getName() +
                            " by pattern " + patternSplit[indexInPattern] +
                            "\n Reason: " + e.getMessage()
                            );
                }
            }
            counter.put(lectureType, counter.get(lectureType) + 1);
        }
    }
}
